package com.yan.qing.bootoss.util;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.EasyExcel;

import com.yan.qing.bootoss.constant.OssConstant;
import com.yan.qing.bootoss.pojo.AliOssInstance;
import com.yan.qing.bootoss.pojo.AliOssProperties;
import lombok.extern.slf4j.Slf4j;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**

 */
@Slf4j
public class ExcelUtil {


    /**
     * 保存文件到本地
     * @param filePath
     * @param dataList
     */
    public static void toFile(String filePath, List<?> dataList) {
        try {
            EasyExcel.write(FileUtil.touch(filePath), dataList.get(0).getClass()).sheet().doWrite(dataList);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new RuntimeException("保存失败...");
        } finally {

        }
    }

    /**
     * 复杂数据导出功能
     *
     * @param filePath
     * @param map
     * @param data
     * @param properties
     * @return
     */
    public static AliOssInstance toAliOss(String filePath, LinkedHashMap<String, String> map, List<?> data, AliOssProperties properties) {
        ByteArrayOutputStream os = null;
        ByteArrayInputStream is = null;
        try {
            os = new ByteArrayOutputStream();
            EasyExcel.write(os)
                    .head(getHeader(map))
                    .sheet("导出数据")
                    .doWrite(getData(map, data));
            is = new ByteArrayInputStream(os.toByteArray());
            String path = StrUtil.concat(true, OssConstant.FILE_PATH_EXCEL_PREFIX, filePath);

            // oss导出
            AliOssInstance aliOssInstance = AliOssInstance.getInstance(
                    properties,
                    is,
                    path,
                    OSSHepler.generateFileName(OssConstant.FILE_EXCEL_SUFFIX)
            );

            aliOssInstance.upload();
            return aliOssInstance;
        } catch (Exception e) {
            log.error(e.getMessage());
            throw new RuntimeException("");
        } finally {
            IoUtil.close(is);
            IoUtil.close(os);
        }
    }

    /**
     * 整合导出信息
     *
     * @param map  已排序的标题信息
     * @param data 需要导出的信息
     * @return
     */
    private static List<List<Object>> getData(LinkedHashMap<String, String> map, List<?> data) {
        // 导出对象
        List<List<Object>> dataList = new ArrayList<>();
        for (Object datum : data) {
            // 导出列数据
            List<Object> columnList = new ArrayList<>();
            try {
                for (Map.Entry<String, String> entry : map.entrySet()) {
                    Field field = datum.getClass().getDeclaredField(entry.getKey());
                    field.setAccessible(true);
                    Object value = field.get(datum);
                    if (value != null && value.getClass().isEnum()) {
                        Method getValueMethod = value.getClass().getMethod("getValue");
                        String propertyValue = getValueMethod.invoke(value).toString();
                        columnList.add(propertyValue);
                    } else {
                        columnList.add(value);
                    }
                }
            } catch (Exception e) {
                log.error(e.getMessage(), e);
                throw new RuntimeException("导出数据出错...");
            }
            dataList.add(columnList);
        }
        return dataList;
    }

    /**
     * 头部标题信息整合
     *
     * @param map 已排序的头部信息
     * @return
     */
    private static List<List<String>> getHeader(LinkedHashMap<String, String> map) {
        List<List<String>> headerList = new ArrayList<>();
        for (Map.Entry<String, String> entry : map.entrySet()) {
            List<String> headerInfos = new ArrayList<>();
            headerInfos.add(entry.getValue());
            headerList.add(headerInfos);
        }
        return headerList;
    }

}
